package com.mfcxy.aop;

import java.lang.reflect.Method;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.beans.factory.annotation.Autowired;

import com.mfcxy.entity.Log;
import com.mfcxy.entity.User;
import com.mfcxy.service.IBaseService;
import com.mfcxy.service.ILogService;
import com.mfcxy.tools.Tools;

/**
 * aop （面向切面编程）实现类
 * 
 * @author mfcxy
 * 
 *         MethodBeforeAdvice。before 方法调用之前 会被调用
 * 
 *         AfterReturningAdvice.afterReturning 返回通知只在普通方法返回时调用
 *
 */
public class ServiceAop implements MethodBeforeAdvice, AfterReturningAdvice {

	@Autowired
	private ServletContext servletContext;
	
	@Autowired  
	private HttpSession session;  

	@Autowired
	private ILogService logService;
	
	@Autowired
	private Tools tools;

	private static Logger logger = Logger.getLogger(ServiceAop.class);

	/**
	 * 目标之后执行的方法
	 * 
	 * @param arg0 returnValue方法返回的值,如果任何
	 * 
	 * @param arg1 方法被调用方法
	 * 
	 * @param arg2 参数的方法
	 * 
	 * @param目标方法调用的目标。可能是{ @code空}。
	 * 
	 */
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		// TODO Auto-generated method stub
		logger.info("之后执行的方法");
		//logger.info("Object = " + arg0);
		//logger.info("Method = " + arg1);
		// logger.info("Object[] = " + arg2[0]);
		 logger.info("Object = " + arg3);

		// 强制类型转换
		IBaseService b = (IBaseService) arg3;
		// 获得类名
		logger.info(b.getClassName());
		
		// 类名拼接上方法名称
		String ClassAndMethod = b.getClassName() + "." + arg1.getName();
		
		logger.info(ClassAndMethod);

		//你考虑日志存在别的数据库可以不是关系型数据库，那些操作要记录日志，你可以考虑配置的方式和注解的方式
		if (!ClassAndMethod.equals("LogService.logsave")) {
			User u = (User) session.getAttribute("user");
			if(u != null) {
				logger.info(u);
				
				Log log = new Log();
				log.setId(tools.getUUID32());
				log.setUid(u.getId());
				log.setUsername(u.getUsername());
				log.setMethod(ClassAndMethod);
				log.setOperationtype("测试"); //采用配置文件或者注解的方式来做操作名称
				logService.logsave(log);
			}
			}
			
	}

	/**
	 * 目标之前执行的方法
	 * 
	 * @param arg0 方法名称
	 * @param arg1 方法参数
	 * @param arg2 目标方法调用的目标。可能是{ @code空}。
	 */
	@Override
	public void before(Method method, Object[] obj1, Object obj2) throws Throwable {
		// TODO Auto-generated method stub
		logger.info("之前执行的方法");
		logger.info("方法名称 = " + method.getName());
//		logger.info("Parameter = " + obj1[0]);
		// logger.info("Object = " + obj2);

	}

}
